#include <n32g45x_usart.h>
#include <usart.h>
#include <rtthread.h>
#include "gpio.h"
usart_cache usart1_cache;
usart_cache usart2_cache;
usart_cache usart3_cache;
usart_cache usart4_cache;
usart_cache usart5_cache;
usart_cache usart6_cache;
usart_cache usart7_cache;

/**/
//	GPIO_ConfigPinRemap(GPIO_RMP_USART1,ENABLE);
//	RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);


void usart1_init(void)
{
    /* Enable GPIO clock */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB | RCC_APB2_PERIPH_AFIO, ENABLE);
    /* Enable USART1 Clock */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_USART1, ENABLE);

    USART_DeInit(USART1);

    NVIC_InitType NVIC_InitStructure;
    /* Configure the NVIC Preemption Priority Bits */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    /* Enable the USART1 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel            = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd         = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    GPIO_ConfigPinRemap(GPIO_RMP_USART1,ENABLE);
//    GPIO_InitType GPIO_InitStructure;
//    /* Configure USART1 Tx as alternate function push-pull */
//    GPIO_InitStructure.Pin        = GPIO_PIN_9;
//    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
//    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
//    /* Configure USART1 Rx as input floating */
//    GPIO_InitStructure.Pin       = GPIO_PIN_10;
//    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

    GPIO_InitType GPIO_InitStructure;
    /* Configure USART3 Tx as alternate function push-pull */
    GPIO_InitStructure.Pin        = GPIO_PIN_6;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
    /* Configure USART3 Rx as input floating */
    GPIO_InitStructure.Pin       = GPIO_PIN_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);

    USART_InitType USART_InitStructure;
    USART_InitStructure.BaudRate            = 115200;
    USART_InitStructure.WordLength          = USART_WL_8B;
    USART_InitStructure.StopBits            = USART_STPB_1;
    USART_InitStructure.Parity              = USART_PE_NO;
    USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
    USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;
    USART_Init(USART1, &USART_InitStructure);

    /* Enable USART1 Receive and Transmit interrupts */
    USART_ConfigInt(USART1, USART_INT_RXDNE, ENABLE);
    USART_ConfigInt(USART1, USART_INT_IDLEF, ENABLE);
//    USART_ConfigInt(USART1, USART_INT_TXDE, ENABLE);

    /* Enable the USART1*/
    USART_Enable(USART1, ENABLE);
    usart1_cache.cnt = 3;
}
void usart2_init(void)
{
    /* Enable GPIO clock */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
    /* Enable USART2 Clock */
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_USART2, ENABLE);

    USART_DeInit(USART2);

    NVIC_InitType NVIC_InitStructure;
    /* Configure the NVIC Preemption Priority Bits */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    /* Enable the USART2 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel            = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd         = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    GPIO_InitType GPIO_InitStructure;
    /* Configure USART2 Tx as alternate function push-pull */
    GPIO_InitStructure.Pin        = GPIO_PIN_2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
    /* Configure USART2 Rx as input floating */
    GPIO_InitStructure.Pin       = GPIO_PIN_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

    USART_InitType USART_InitStructure;
    USART_InitStructure.BaudRate            = 9600;
    USART_InitStructure.WordLength          = USART_WL_8B;
    USART_InitStructure.StopBits            = USART_STPB_1;
    USART_InitStructure.Parity              = USART_PE_NO;
    USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
    USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;
    USART_Init(USART2, &USART_InitStructure);

    /* Enable USART2 Receive and Transmit interrupts */
    USART_ConfigInt(USART2, USART_INT_RXDNE, ENABLE);
    USART_ConfigInt(USART2, USART_INT_IDLEF, ENABLE);
//    USART_ConfigInt(USART2, USART_INT_TXDE, ENABLE);

    /* Enable the USART2*/
    USART_Enable(USART2, ENABLE);
    usart2_cache.cnt = 3;
}

void usart3_init(void)
{
    /* Enable GPIO clock */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);
    /* Enable USART3 Clock */
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_USART3, ENABLE);

    USART_DeInit(USART3);

    NVIC_InitType NVIC_InitStructure;
    /* Configure the NVIC Preemption Priority Bits */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    /* Enable the USART3 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel            = USART3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd         = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    GPIO_InitType GPIO_InitStructure;
    /* Configure USART3 Tx as alternate function push-pull */
    GPIO_InitStructure.Pin        = GPIO_PIN_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
    /* Configure USART3 Rx as input floating */
    GPIO_InitStructure.Pin       = GPIO_PIN_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);

    USART_InitType USART_InitStructure;
    USART_InitStructure.BaudRate            = 9600;
    USART_InitStructure.WordLength          = USART_WL_8B;
    USART_InitStructure.StopBits            = USART_STPB_1;
    USART_InitStructure.Parity              = USART_PE_NO;
    USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
    USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;
    USART_Init(USART3, &USART_InitStructure);

    /* Enable USART3 Receive and Transmit interrupts */
    USART_ConfigInt(USART3, USART_INT_RXDNE, ENABLE);
    USART_ConfigInt(USART3, USART_INT_IDLEF, ENABLE);
//    USART_ConfigInt(USART3, USART_INT_TXDE, ENABLE);

    /* Enable the USART3*/
    USART_Enable(USART3, ENABLE);
    usart3_cache.cnt = 3;
}

void usart4_init(void)
{
    /* Enable GPIO clock */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE);
    /* Enable USART4 Clock */
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_UART4, ENABLE);

    USART_DeInit(UART4);

    NVIC_InitType NVIC_InitStructure;
    /* Configure the NVIC Preemption Priority Bits */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    /* Enable the USART4 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel            = UART4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd         = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    GPIO_InitType GPIO_InitStructure;
    /* Configure USART4 Tx as alternate function push-pull */
    GPIO_InitStructure.Pin        = GPIO_PIN_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure);
    /* Configure USART4 Rx as input floating */
    GPIO_InitStructure.Pin       = GPIO_PIN_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure);

    USART_InitType USART_InitStructure;
    USART_InitStructure.BaudRate            = 9600;
    USART_InitStructure.WordLength          = USART_WL_8B;
    USART_InitStructure.StopBits            = USART_STPB_1;
    USART_InitStructure.Parity              = USART_PE_NO;
    USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
    USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;
    USART_Init(UART4, &USART_InitStructure);

    /* Enable USART4 Receive and Transmit interrupts */
    USART_ConfigInt(UART4, USART_INT_RXDNE, ENABLE);
    USART_ConfigInt(UART4, USART_INT_IDLEF, ENABLE);
//    USART_ConfigInt(USART4, USART_INT_TXDE, ENABLE);

    /* Enable the USART4*/
    USART_Enable(UART4, ENABLE);
    usart4_cache.cnt = 3;
}

void usart5_init(void)
{
    /* Enable GPIO clock */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE);
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE);
    /* Enable USART5 Clock */
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_UART5, ENABLE);

    USART_DeInit(UART5);

    NVIC_InitType NVIC_InitStructure;
    /* Configure the NVIC Preemption Priority Bits */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    /* Enable the USART5 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel            = UART5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd         = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    GPIO_InitType GPIO_InitStructure;
    /* Configure USART5 Tx as alternate function push-pull */
    GPIO_InitStructure.Pin        = GPIO_PIN_12;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure);
    /* Configure USART5 Rx as input floating */
    GPIO_InitStructure.Pin       = GPIO_PIN_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitPeripheral(GPIOD, &GPIO_InitStructure);

    USART_InitType USART_InitStructure;
    USART_InitStructure.BaudRate            = 115200;
    USART_InitStructure.WordLength          = USART_WL_8B;
    USART_InitStructure.StopBits            = USART_STPB_1;
    USART_InitStructure.Parity              = USART_PE_NO;
    USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
    USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;
    USART_Init(UART5, &USART_InitStructure);

    /* Enable USART5 Receive and Transmit interrupts */
    USART_ConfigInt(UART5, USART_INT_RXDNE, ENABLE);
    USART_ConfigInt(UART5, USART_INT_IDLEF, ENABLE);
//    USART_ConfigInt(USART5, USART_INT_TXDE, ENABLE);

    /* Enable the USART5*/
    USART_Enable(UART5, ENABLE);
    usart5_cache.cnt = 3;
}

void usart6_init(void)
{
    /* Enable GPIO clock */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE);
    /* Enable USART5 Clock */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_UART6, ENABLE);

    USART_DeInit(UART6);

    NVIC_InitType NVIC_InitStructure;
    /* Configure the NVIC Preemption Priority Bits */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    /* Enable the USART5 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel            = UART6_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd         = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    GPIO_InitType GPIO_InitStructure;
    /* Configure USART5 Tx as alternate function push-pull */
    GPIO_InitStructure.Pin        = GPIO_PIN_2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitPeripheral(GPIOE, &GPIO_InitStructure);
    /* Configure USART5 Rx as input floating */
    GPIO_InitStructure.Pin       = GPIO_PIN_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitPeripheral(GPIOE, &GPIO_InitStructure);

    USART_InitType USART_InitStructure;
    USART_InitStructure.BaudRate            = 9600;
    USART_InitStructure.WordLength          = USART_WL_8B;
    USART_InitStructure.StopBits            = USART_STPB_1;
    USART_InitStructure.Parity              = USART_PE_NO;
    USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
    USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;
    USART_Init(UART6, &USART_InitStructure);

    /* Enable USART5 Receive and Transmit interrupts */
    USART_ConfigInt(UART6, USART_INT_RXDNE, ENABLE);
    USART_ConfigInt(UART6, USART_INT_IDLEF, ENABLE);
//    USART_ConfigInt(USART5, USART_INT_TXDE, ENABLE);

    /* Enable the USART5*/
    USART_Enable(UART6, ENABLE);
    usart6_cache.cnt = 3;
}
void usart7_init(void)
{
    /* Enable GPIO clock */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE);
    /* Enable USART5 Clock */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_UART7, ENABLE);

    USART_DeInit(UART7);

    NVIC_InitType NVIC_InitStructure;
    /* Configure the NVIC Preemption Priority Bits */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    /* Enable the USART5 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel            = UART7_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd         = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    GPIO_InitType GPIO_InitStructure;
    /* Configure USART5 Tx as alternate function push-pull */
    GPIO_InitStructure.Pin        = GPIO_PIN_4;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure);
    /* Configure USART5 Rx as input floating */
    GPIO_InitStructure.Pin       = GPIO_PIN_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure);

    USART_InitType USART_InitStructure;
    USART_InitStructure.BaudRate            = 9600;
    USART_InitStructure.WordLength          = USART_WL_8B;
    USART_InitStructure.StopBits            = USART_STPB_1;
    USART_InitStructure.Parity              = USART_PE_NO;
    USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
    USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;
    USART_Init(UART7, &USART_InitStructure);

    /* Enable USART5 Receive and Transmit interrupts */
    USART_ConfigInt(UART7, USART_INT_RXDNE, ENABLE);
    USART_ConfigInt(UART7, USART_INT_IDLEF, ENABLE);
//    USART_ConfigInt(USART5, USART_INT_TXDE, ENABLE);

    /* Enable the USART5*/
    USART_Enable(UART7, ENABLE);
    usart7_cache.cnt = 3;
}

uint8_t usart_trans(USART_Module* USARTx, uint8_t* Data, uint16_t DataLen)
{
    for(uint32_t i = 0 ; i < DataLen; i++) {
        USART_SendData(USARTx, Data[i]);
        while (USART_GetFlagStatus(USARTx, USART_FLAG_TXDE) == RESET)
        {
        }
    }
    return 0;
}

uint8_t usart_485initial(Type485 Name485)
{
    switch(Name485) {
    case BACKUP_485:
//        gpio_init_out(GPIOA, GPIO_PIN_1);
//        gpio_off(GPIOA, GPIO_PIN_1);
        break;
    case CNN_485:
        gpio_init_out(GPIOB, GPIO_PIN_2);
        gpio_off(GPIOB, GPIO_PIN_2);
        break;
    }
}
uint8_t usart_485trans(Type485 Name485, uint8_t* Data, uint16_t DataLen)
{
    switch(Name485) {
    case BACKUP_485:
//        gpio_on(GPIOA, GPIO_PIN_1);
        rt_thread_delay(10);
        usart_trans(USART2, &Data[0], DataLen);
        rt_thread_delay(10);
//        gpio_off(GPIOA, GPIO_PIN_1);
        break;
    case CNN_485:
        gpio_on(GPIOB, GPIO_PIN_2);
        rt_thread_delay(10);
        usart_trans(USART3, &Data[0], DataLen);
        rt_thread_delay(10);
        gpio_off(GPIOB, GPIO_PIN_2);
        break;
    }
}